using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;
using MediPlatform.Read.Api.Models;

namespace MediPlatform.Read.Api.Services
{
    /// <summary>
    /// JWT服务
    /// </summary>
    public class JwtService
    {
        private readonly IConfiguration _configuration;

        public JwtService(IConfiguration configuration)
        {
            _configuration = configuration;
        }

        /// <summary>
        /// 生成访问令牌
        /// </summary>
        /// <param name="user">用户信息</param>
        /// <returns>访问令牌</returns>
        public string GenerateAccessToken(UserInfo user)
        {
            var tokenHandler = new JwtSecurityTokenHandler();
            var key = Encoding.ASCII.GetBytes(_configuration["Jwt:SecretKey"] ?? "YourSuperSecretKey12345678901234567890");

            var claims = new List<Claim>
            {
                new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
                new Claim(ClaimTypes.Name, user.Username),
                new Claim(ClaimTypes.Email, user.Email),
                new Claim(ClaimTypes.Role, user.Role),
                new Claim("UserId", user.UserId),
                new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
                new Claim(JwtRegisteredClaimNames.Iat, DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64)
            };

            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(claims),
                Expires = DateTime.UtcNow.AddMinutes(Convert.ToInt32(_configuration["Jwt:AccessTokenExpirationMinutes"] ?? "30")),
                Issuer = _configuration["Jwt:Issuer"] ?? "MediPlatform",
                Audience = _configuration["Jwt:Audience"] ?? "MediPlatformUsers",
                SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
            };

            var token = tokenHandler.CreateToken(tokenDescriptor);
            return tokenHandler.WriteToken(token);
        }

        /// <summary>
        /// 生成刷新令牌
        /// </summary>
        /// <returns>刷新令牌</returns>
        public string GenerateRefreshToken()
        {
            var randomNumber = new byte[64];
            using var rng = RandomNumberGenerator.Create();
            rng.GetBytes(randomNumber);
            return Convert.ToBase64String(randomNumber);
        }

        /// <summary>
        /// 验证访问令牌
        /// </summary>
        /// <param name="token">访问令牌</param>
        /// <returns>用户信息</returns>
        public UserInfo? ValidateAccessToken(string token)
        {
            var tokenHandler = new JwtSecurityTokenHandler();
            var key = Encoding.ASCII.GetBytes(_configuration["Jwt:SecretKey"] ?? "YourSuperSecretKey12345678901234567890");

            try
            {
                tokenHandler.ValidateToken(token, new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(key),
                    ValidateIssuer = true,
                    ValidIssuer = _configuration["Jwt:Issuer"] ?? "MediPlatform",
                    ValidateAudience = true,
                    ValidAudience = _configuration["Jwt:Audience"] ?? "MediPlatformUsers",
                    ValidateLifetime = true,
                    ClockSkew = TimeSpan.Zero
                }, out SecurityToken validatedToken);

                var jwtToken = (JwtSecurityToken)validatedToken;

                return new UserInfo
                {
                    Id = long.Parse(jwtToken.Claims.First(x => x.Type == ClaimTypes.NameIdentifier).Value),
                    Username = jwtToken.Claims.First(x => x.Type == ClaimTypes.Name).Value,
                    Email = jwtToken.Claims.First(x => x.Type == ClaimTypes.Email).Value,
                    Role = jwtToken.Claims.First(x => x.Type == ClaimTypes.Role).Value,
                    UserId = jwtToken.Claims.First(x => x.Type == "UserId").Value,
                    CreatedAt = DateTime.Parse(jwtToken.Claims.First(x => x.Type == JwtRegisteredClaimNames.Iat).Value)
                };
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// 从令牌中获取用户ID
        /// </summary>
        /// <param name="token">访问令牌</param>
        /// <returns>用户ID</returns>
        public long? GetUserIdFromToken(string token)
        {
            var user = ValidateAccessToken(token);
            return user?.Id;
        }

        /// <summary>
        /// 从令牌中获取用户名
        /// </summary>
        /// <param name="token">访问令牌</param>
        /// <returns>用户名</returns>
        public string? GetUsernameFromToken(string token)
        {
            var user = ValidateAccessToken(token);
            return user?.Username;
        }

        /// <summary>
        /// 从令牌中获取角色
        /// </summary>
        /// <param name="token">访问令牌</param>
        /// <returns>角色</returns>
        public string? GetRoleFromToken(string token)
        {
            var user = ValidateAccessToken(token);
            return user?.Role;
        }
    }
} 